<?php

$data = [
    [
        'date' => '2023-01-01',
        'area' => '0000',
        'name' => 'tim',
        'amount' => 1,
        'price' => 10,
        'total' => 19
    ],
    [
        'date' => '2023-01-02',
        'area' => '0000',
        'name' => 'tim',
        'amount' => 3,
        'price' => 11,
        'total' => 22
    ],
    [
        'date' => '2023-01-01',
        'area' => '0001',
        'name' => 'tom',
        'amount' => 11,
        'price' => 11,
        'total' => 1
    ],
    [
        'date' => '2023-02-01',
        'area' => '0011',
        'name' => 'tim',
        'amount' => 6,
        'price' => 11,
        'total' => 13
    ],
    [
        'date' => '2023-01-01',
        'area' => '0000',
        'name' => 'jerry',
        'amount' => 3,
        'price' => 40,
        'total' => 122
    ],
    [
        'date' => '2023-01-02',
        'area' => '0001',
        'name' => 'jerry',
        'amount' => 1,
        'price' => 31,
        'total' => 19
    ],
    [
        'date' => '2023-01-02',
        'area' => '0002',
        'name' => 'jerry',
        'amount' => 3,
        'price' => 13,
        'total' => 111
    ],
];
function array_group_by(array $arr, $key) : array
{
    if (!is_string($key) && !is_int($key) && !is_float($key) && !is_callable($key)) {
        trigger_error('array_group_by(): The key should be a string, an integer, a float, or a function', E_USER_ERROR);
    }

    $isFunction = !is_string($key) && is_callable($key);

    // Load the new array, splitting by the target key
    $grouped = [];
    foreach ($arr as $value) {
        $groupKey = null;

        if ($isFunction) {
            $groupKey = $key($value);
        } else if (is_object($value)) {
            $groupKey = $value->{$key};
        } else {
            $groupKey = $value[$key];
        }
        if (func_num_args() == 2) {
            // todo: value aggr
            var_dump($value);
        }
        $grouped[$groupKey][] = $value;
    }

    // Recursively build a nested grouping if more parameters are supplied
    // Each grouped array value is grouped according to the next sequential key
    if (func_num_args() > 2) {
        $args = func_get_args();

        foreach ($grouped as $groupKey => $value) {
            $params = array_merge([$value], array_slice($args, 2, func_num_args()));
            $grouped[$groupKey] = call_user_func_array('array_group_by', $params);
        }
    }

    return $grouped;
}
var_dump(json_encode(array_group_by($data, 'name', 'area', 'date')));